package com.zzyl.nursing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.bean.BeanUtils;
import com.zzyl.nursing.domain.NursingLevel;
import com.zzyl.nursing.domain.NursingPlan;
import com.zzyl.nursing.domain.NursingProjectPlan;
import com.zzyl.nursing.dot.NursingPlanDto;
import com.zzyl.nursing.mapper.NursingPlanMapper;
import com.zzyl.nursing.service.INursingLevelService;
import com.zzyl.nursing.service.INursingPlanService;
import com.zzyl.nursing.service.INursingProjectPlanService;
import com.zzyl.nursing.vo.NursingPlanVo;
import com.zzyl.nursing.vo.NursingProjectPlanVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 护理计划Service业务层处理
 *
 * @author zgp
 * @date 2025-02-21
 */
@Service
public class NursingPlanServiceImpl extends ServiceImpl<NursingPlanMapper, NursingPlan> implements INursingPlanService {
    @Autowired
    private NursingPlanMapper nursingPlanMapper;
    @Autowired
    private INursingProjectPlanService nursingProjectPlanService;
    @Autowired
    private INursingLevelService nursingLevelService;

    /**
     * 查询护理计划
     *
     * @param id 护理计划主键
     * @return 护理计划VO
     */
    @Override
    public NursingPlanVo selectNursingPlanById(Long id) {
        // 查询护理计划基本信息
        NursingPlan nursingPlan = getById(id);
        // 查询护理计划对应护理项目
        List<NursingProjectPlan> projectPlans = nursingProjectPlanService.list(
                Wrappers.<NursingProjectPlan>lambdaQuery()
                        .eq(NursingProjectPlan::getPlanId, id));
        NursingPlanVo vo = BeanUtil.toBean(nursingPlan, NursingPlanVo.class);
        List<NursingProjectPlanVo> projectPlanVos = BeanUtil.copyToList(projectPlans, NursingProjectPlanVo.class);
        vo.setProjectPlans(projectPlanVos);
        return vo;
    }

    /**
     * 查询护理计划列表
     *
     * @param nursingPlan 护理计划
     * @return 护理计划
     */
    @Override
    public List<NursingPlan> selectNursingPlanList(NursingPlan nursingPlan) {
        return nursingPlanMapper.selectNursingPlanList(nursingPlan);
    }

    /**
     * 新增护理计划
     *
     * @param nursingPlanDto 护理计划DTO
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int insertNursingPlan(NursingPlanDto nursingPlanDto) {
        // 保存护理计划基本信息
        NursingPlan nursingPlan = new NursingPlan();
        BeanUtils.copyProperties(nursingPlanDto, nursingPlan);
        save(nursingPlan);

        // 保存护理计划对应护理项目信息
        List<NursingProjectPlan> projectPlans = nursingPlanDto.getProjectPlans();
        projectPlans.forEach(o -> o.setPlanId(nursingPlan.getId()));
        return nursingProjectPlanService.saveBatch(projectPlans) ? 1 : 0;
    }

    /**
     * 修改护理计划
     *
     * @param nursingPlanDto 护理计划DTO
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateNursingPlan(NursingPlanDto nursingPlanDto) {
        // 业务校验：与护理等级绑定的护理计划禁止修改
        List<NursingLevel> nursingLevels = nursingLevelService.list(
                new LambdaQueryWrapper<NursingLevel>()
                        .eq(NursingLevel::getLplanId, nursingPlanDto.getId()));
        if(CollUtil.isNotEmpty(nursingLevels)){
            throw new BaseException("操作失败，当前护理计划已与护理等级绑定");
        }
        // 修改护理计划基本信息
        NursingPlan nursingPlan = BeanUtil.toBean(nursingPlanDto, NursingPlan.class);
        boolean flag = updateById(nursingPlan);
        if(!flag){
            throw new BaseException("保存护理计划基本信息失败");
        }
        List<NursingProjectPlan> paramProjectPlans = nursingPlanDto.getProjectPlans();
        if(CollUtil.isNotEmpty(nursingPlanDto.getProjectPlans())){
            // 删除原护理计划对应的护理项目信息
            flag = nursingProjectPlanService.remove(
                    Wrappers.<NursingProjectPlan>lambdaQuery()
                            .eq(NursingProjectPlan::getPlanId, nursingPlan.getId()));
            if(!flag){
                throw new BaseException("删除护理计划对应护理项目信息失败");
            }
            // 保存修改后的护理计划对应的项目信息
            List<NursingProjectPlan> projectPlans = BeanUtil.copyToList(paramProjectPlans, NursingProjectPlan.class);
            projectPlans.forEach(o -> o.setPlanId(nursingPlan.getId()));
            flag = nursingProjectPlanService.saveBatch(projectPlans);
            if(!flag){
                throw new BaseException("保存护理计划对应护理项目信息失败");
            }
        }
        return 1;
    }

    /**
     * 批量删除护理计划
     *
     * @param ids 需要删除的护理计划主键
     * @return 结果
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int deleteNursingPlanByIds(Long[] ids) {
        // 业务校验：与护理等级绑定的护理计划禁止删除
        LambdaQueryWrapper<NursingLevel> qw = new LambdaQueryWrapper<>();
        qw.in(NursingLevel::getLplanId, ids);
        List<NursingLevel> nursingLevels = nursingLevelService.list(qw);
        if(CollUtil.isNotEmpty(nursingLevels)){
            throw new BaseException("删除失败，当前护理计划已与护理等级绑定");
        }
        // 删除护理计划基本信息
        boolean flag = removeBatchByIds(Arrays.asList(ids));
        if(!flag){
            throw new BaseException("删除护理计划失败");
        }
        // 删除护理计划对应护理项目信息
        List<Integer> nursingProjectPlanIds = nursingProjectPlanService.list(
                        Wrappers.<NursingProjectPlan>lambdaQuery().in(NursingProjectPlan::getPlanId, ids)
                ).stream()
                .map(o -> o.getId())
                .collect(Collectors.toList());
        flag = nursingProjectPlanService.removeBatchByIds(nursingProjectPlanIds);
        if(!flag){
            throw new BaseException("删除护理计划对应护理项目信息失败");
        }
        return 1;
    }

    /**
     * 删除护理计划信息
     *
     * @param id 护理计划主键
     * @return 结果
     */
    @Override
    public int deleteNursingPlanById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    @Override
    public List<NursingPlan> getAllByStatus(int i) {
        return this.list(new LambdaQueryWrapper<NursingPlan>().eq(NursingPlan::getStatus, i));
    }
}
